package com.tian.okhttp.upload

import okhttp3.*
import okhttp3.Headers.Companion.toHeaders
import okio.BufferedSink
import java.io.File
import java.io.FileInputStream
import java.io.IOException
import java.util.concurrent.TimeUnit

/**
 * @author tiansongtao, Email:tiansongtao@up366.com
 * @date 2021/4/9 11:48
 */
object OkHttpUploadFile {

    private val httpClient: OkHttpClient by lazy {
        var build = OkHttpClient.Builder()
            .connectTimeout(30, TimeUnit.SECONDS)
            .writeTimeout(40, TimeUnit.SECONDS)
            .readTimeout(30, TimeUnit.SECONDS)

        build.build()
    }


    fun post(uploadParams: UploadParams) {
        //TODO 主线程处理，后续添加
        startUpload(uploadParams)
    }

    /**
     * 开始上传文件
     */
    private fun startUpload(uploadParams: UploadParams) {
        val checkResult = checkUploadParams(uploadParams)
        if (checkResult.isNotEmpty()) {
            uploadParams.uploadCallback(UploadParams.State.FAILED, 0, 0, checkResult)
            return
        }
        val file = File(uploadParams.filePath)
        val totalLength = file.length()

        val requestBody = object : RequestBody() {
            override fun contentType(): MediaType? {
                return null
            }

            override fun writeTo(sink: BufferedSink) {
                val inputStream = FileInputStream(file)
                var uploadedLength = 0L
                val bytes = ByteArray(2048)
                val uploadPercent = 0
                var len: Int
                val currentTime = System.currentTimeMillis()
                while ((inputStream.read(bytes).also { len = it }) != -1) {
                    sink.write(bytes, 0, len)
                    uploadedLength += len
                    val percent: Int = (uploadedLength * 100 / totalLength).toInt()
                    if ((percent != uploadPercent && (System.currentTimeMillis() - currentTime) > 345) || percent == 100) {
                        uploadParams.uploadCallback(
                            UploadParams.State.UPLOADING,
                            uploadedLength,
                            totalLength,
                            ""
                        )
                    }
                }

            }

        }


        val bodyBuilder = MultipartBody.Builder()
        val bodyParams = mutableMapOf<String, String>()
        uploadParams.initParams(bodyParams)
        if (bodyParams.isNotEmpty()) {
            for (entry in bodyParams.entries) {
                bodyBuilder.addFormDataPart(entry.key, entry.value)
            }
        }
        bodyBuilder.addFormDataPart(uploadParams.uploadFileKey, file.name, requestBody)

        val requestHeaders = mutableMapOf<String, String>()
        uploadParams.initHeaders(requestHeaders)
        val headers = requestHeaders.toHeaders()
        val request = Request.Builder()
            .url(uploadParams.url)
            .headers(headers)
            .post(bodyBuilder.build())
            .build()

        uploadParams.uploadCallback(UploadParams.State.START, 0, totalLength, "")
        httpClient.newCall(request).enqueue(object : Callback {
            override fun onFailure(call: Call, e: IOException) {

            }

            override fun onResponse(call: Call, response: Response) {

            }
        })
    }

    private fun checkUploadParams(uploadParams: UploadParams): String {
        if (uploadParams.filePath.isEmpty() || uploadParams.uploadFileKey.isEmpty()
            || uploadParams.url.isEmpty()
        ) {
            return "参数错误"
        }
        val file = File(uploadParams.filePath)
        if (!file.exists()) {
            return "文件不存在"
        }
        return ""
    }


}